﻿using System;
using System.Collections.Generic;

namespace Communication.Help;

public static class SpanHelp
{
    /// <summary>
    ///     对Span中的每个元素应用指定的转换函数，并返回修改后的Span
    /// </summary>
    /// <typeparam name="T">Span元素的类型</typeparam>
    /// <param name="span">原始的Span对象</param>
    /// <param name="selector">应用于每个元素的转换函数</param>
    /// <returns>经过转换后的Span对象</returns>
    public static Span<T> Select<T>(this Span<T> span, Func<T, T> selector)
    {
        // 遍历Span中的每个元素
        for (var i = 0; i < span.Length; i++)
            // 对当前元素应用转换函数，并将结果存回原位置
            span[i] = selector(span[i]);
        // 返回修改后的Span
        return span;
    }


    /// <summary>
    ///     将数组按条件分组
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="arr"></param>
    /// <param name="checkContinuity">判断两个数据间隔</param>
    /// <param name="validateLength">长度分割 第一个数据和最后一个数据</param>
    /// <returns></returns>
    public static List<T[]> SplitIntoGroups<T>(this List<T>? arr, Func<T, T, bool> checkContinuity,
        Func<T, T, bool>? validateLength = null)
    {
        // 创建一个空的分组列表
        var groups = new List<T[]>();
        // 如果数组为空或长度为0，则返回空的分组列表
        if (arr == null || arr.Count == 0) return groups;
        // 创建一个当前分组的列表，并将第一个元素添加进去
        var currentGroup = new List<T> { arr[0] };
        // 遍历数组，从第二个元素开始
        for (var i = 1; i < arr.Count; i++)
        {
            // 如果验证长度为空或验证长度函数返回true，并且检查连续性函数返回true，则将当前元素添加到当前分组
            if ((validateLength is null || validateLength(currentGroup[0], arr[i])) &&
                checkContinuity(arr[i], arr[i - 1]))
            {
                currentGroup.Add(arr[i]);
            }
            // 否则，将当前分组添加到分组列表，并创建一个新的当前分组，将当前元素添加进去
            else
            {
                groups.Add([.. currentGroup]);
                currentGroup = [arr[i]];
            }
        }

        // 将最后一个分组添加到分组列表
        groups.Add([.. currentGroup]);
        // 返回分组列表
        return groups;
    }
}